﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Microsoft Corp." file="CopyFilesOperation.cs">
//   All rights reserved. See License.txt in the project root for license information.
// </copyright>
// 
// --------------------------------------------------------------------------------------------------------------------
namespace CloudBlitz.DeploymentManager.DeploymentOperations
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Threading.Tasks;

    using CloudBlitz.DeploymentManager.DeploymentWorkflow;

    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;

    public class CopyFilesOperation : DeploymentOperationBase
    {
        private const string ServiceConfigurationFileName = "ServiceConfiguration.Cloud.cscfg";

        private const string ServiceDefinitionFileName = "ServiceDefinition.csdef";

        private readonly Func<LocalResource> localResourceFactory;

        public CopyFilesOperation(Func<LocalResource> locaResourceFactory) : base(1)
        {
            this.localResourceFactory = locaResourceFactory;
        }

        protected override OperationResult ExecuteOverride(DeploymentContext context)
        {
            try
            {
                this.RaiseProgressChangedEvent(0, "Copying cluster package files to the local resource");

                var cloudStorageAccount = CloudStorageAccount.Parse(context.UserStorageConnectionString);

                var cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();

                var localResource = this.localResourceFactory();

                context.ClusterDetails.ServiceConfigurationFilePath = Path.Combine(localResource.RootPath, ServiceConfigurationFileName);
                context.ClusterDetails.ServiceDefinitionFilePath = Path.Combine(localResource.RootPath, ServiceDefinitionFileName);

                var blobRequestOptions = new BlobRequestOptions
                {
                    RetryPolicy = RetryPolicies.RetryExponential(3, TimeSpan.FromMinutes(3))
                };

                var storageFiles = new Dictionary<CloudBlob, string>
                {
                    { cloudBlobClient.GetBlobReference(context.ClusterPackageDetails.CscfgFile), context.ClusterDetails.ServiceConfigurationFilePath },
                    { cloudBlobClient.GetBlobReference(context.ClusterPackageDetails.CsdefFile), context.ClusterDetails.ServiceDefinitionFilePath }
                };

                Parallel.ForEach(storageFiles, storageBlob => storageBlob.Key.DownloadToFile(storageBlob.Value, blobRequestOptions));

                this.RaiseProgressChangedEvent(100, "Cluster package files copied to the local resource");
                return OperationResult.Success;
            }
            catch (StorageClientException e)
            {
                return new OperationResult(DeploymentOperationStatus.Failed, e.Message);
            }
            catch (Exception e)
            {
                return ExceptionHelper.HandleException(e);
            }
        }
    }
}